using System;
using System.Collections;
using System.Xml;

namespace FreeFlow.Client
{
	/// <summary>
	/// View onto a read-only folder at a stage
	/// </summary>
  [Serializable]
  public class FolderPage : Connectable, IFolder 
  {
    private System.Collections.Generic.List<string> formNames;
    private Hashtable forms;
    private System.Collections.Generic.List<Action> actions;
    /// <summary>
    /// Creates a new <see cref="FolderPage"/> instance.
    /// </summary>
    public FolderPage()
    {
      formNames = new System.Collections.Generic.List<string>();
      forms = new Hashtable();
      actions = new System.Collections.Generic.List<Action>();
    }

    #region properties
    private string folderId;
    /// <summary>
    /// Gets or sets the folder id.
    /// </summary>
    public string FolderId
    {
      get
      {
        return folderId;
      }
      set
      {
        folderId = value;
        Populate();
      }
    }

    private string folderName;
    /// <summary>
    /// Gets the name of the folder.
    /// </summary>
    public string FolderName
    {
      get
      {
        return folderName;
      }
    }

    private string mapName;
    /// <summary>
    /// Gets the name of the map that this folder is an instance of.
    /// </summary>
    public string MapName
    {
      get
      {
        return mapName;
      }
    }

    private string stageName;
    /// <summary>
    /// Gets the name of the stage that the folder is currently at.
    /// </summary>
    public string StageName
    {
      get
      {
        return stageName;
      }
    }

    #endregion
    #region forms
    /// <summary>
    /// Gets the number of forms in the folder.
    /// </summary>
    public int FormCount
    {
      get
      {
        return formNames.Count;
      }
    }

    /// <summary>
    /// Returns the name of the form at the specified index.
    /// </summary>
    /// <param name="index">Index.</param>
    public string FormName(int index)
    {
      return formNames[index];
    }

    /// <summary>
    /// Returns the Forms at the specified index. If the form hasn't been retrieved will require
    /// a call to the engine.
    /// </summary>
    /// <param name="index">Index.</param>
    public Form Form(int index)
    {
      return Form(FormName(index));
    }

    /// <summary>
    /// Returns the Forms with the specified name. If the form hasn't been retrieved will require
    /// a call to the engine.
    /// </summary>
    /// <param name="formName">Name of the form.</param>
    public Form Form(string formName)
    {
      if (forms[formName] == null)
      {
        // request other form if not already requested
        Populate(formName);
      }
      return forms[formName] as Form;
    }
    #endregion
    #region actions
    /// <summary>
    /// Gets the number of actions available for this folder.
    /// </summary>
    public int ActionCount
    {
      get
      {
        return actions.Count;
      }
    }

    /// <summary>
    /// Returns the action at the specified index.
    /// </summary>
    /// <param name="index">Index.</param>
    public Action Action(int index)
    {
      return (Action)actions[index];
    }

    /// <summary>
    /// Returns the action with the specified name.
    /// </summary>
    /// <param name="name">Name.</param>
    public Action Action(string name)
    {
      for (int i = 0; i < ActionCount; i++)
      {
        if (Action(i).Name == name)
          return Action(i);
      }

      return null;
    }
    #endregion

    private void Populate()
    {
      Populate(null);
    }

    private void Populate(string formName)
    {
      CheckConnection();

      if (folderId != null)
      {
        // create the request
        XmlDocument req = new XmlDocument();
        XmlElement docElem = req.CreateElement("eFolderRequest");
        docElem.SetAttribute("FolderID", folderId);
        if (formName != null)
          docElem.SetAttribute("Form", formName);

        req.AppendChild(docElem);

        XmlDocument doc = Connection.SendDecoratedMsg(req);

        // get the forms in the folder
        formNames.Clear();
 
        XmlNode formsNode = doc.DocumentElement.GetElementsByTagName("FolderPageList")[0];
        folderName = doc.DocumentElement.GetAttribute("Folder");
        mapName = doc.DocumentElement.GetAttribute("Map");
        stageName = doc.DocumentElement.GetAttribute("Stage");

        if (formsNode != null)
        {
          foreach (XmlElement formNode in formsNode.ChildNodes)
          {
            formNames.Add(formNode.GetAttribute("Form"));
          }
        }

        XmlElement formLayoutNode = doc.DocumentElement[FreeFlow.Client.Form.FormLayoutElement];
        if (formLayoutNode != null)
        {
          Form thisForm = new Form(formLayoutNode, Connection);
          thisForm.Connection = Connection;
          thisForm.Page = this;
          thisForm.FillValues(doc.DocumentElement["FieldOutputList"]);
          forms.Add(thisForm.Name, thisForm);
        }

        // available actions
        actions.Clear();
        XmlElement actionsNode = doc.DocumentElement["FolderActionList"];
        if (actionsNode != null)
        {
          foreach (XmlElement actionNode in actionsNode.ChildNodes)
          {
            Action action = new Action(actionNode.GetAttribute("Action"), 
              actionNode.GetAttribute("Type"));
            actions.Add(action);
          }
        }
      }
    }
  }
}
